// ViewBriefingState.cpp: implementation of the ViewBriefingState class.
//
//////////////////////////////////////////////////////////////////////

#include "ViewBriefingState.h"
#include "LoadBriefingState.h"

#ifdef FREEGLUT_IS_PRESENT
#  include <GL/freeglut.h>
#else
#  ifdef __APPLE__
#    include <GLUT/glut.h>
#  else
#    include <GL/glut.h>
#  endif
#endif

#include <plib/pu.h>
#include <plib/puAux.h>
#include <plib/fnt.h>
#include <plib/js.h>

#include "BackGroundImage.h"
#include "ImageButton.h"
#include "VideoImage.h"
#include "ProgressBar.h"
#include "Keyboard.h"
#include "Joystick.h"
#include "Mouse.h"
#include "Land.h"
#include "Movie.h"
#include "Scenegraph.h"
#include "FPSTest.h"
#include "ObjectList.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

ViewBriefingState::ViewBriefingState(State* os,LoadingInfo* li)
{
ck = new ulClock;
float dt = 0.0f;
bool canceled = false;
v = 1;

readBriefingFile(li);

this->info = li;

this->oldState = os;

int wh = li->h;//(float)glutGet ( (GLenum) GLUT_WINDOW_HEIGHT ) ;
int ww = li->w;//(float)glutGet ( (GLenum) GLUT_WINDOW_WIDTH  ) ;

// player controls
this->player = new puGroup(0,0);
this->player -> setUserData((void*)this);

int sx = (li->w / 2) - (NUM_PLAYER_BUTTONS / 2);

rewindButton	= new puArrowButton(sx							,PLAYER_START_Y,sx + 1*PLAYER_BUTTON_WIDTH,PLAYER_START_Y + PLAYER_BUTTON_HEIGTH,PUARROW_FASTLEFT);
stopButton		= new puArrowButton(sx + 1*PLAYER_BUTTON_WIDTH	,PLAYER_START_Y,sx + 2*PLAYER_BUTTON_WIDTH,PLAYER_START_Y + PLAYER_BUTTON_HEIGTH,PUARROW_DOWN);
stopButton      -> setCallback(stopm_cb);
playButton		= new puArrowButton(sx + 2*PLAYER_BUTTON_WIDTH	,PLAYER_START_Y,sx + 3*PLAYER_BUTTON_WIDTH,PLAYER_START_Y + PLAYER_BUTTON_HEIGTH,PUARROW_RIGHT);
playButton		-> setCallback(playm_cb);
forwardButton	= new puArrowButton(sx + 3*PLAYER_BUTTON_WIDTH	,PLAYER_START_Y,sx + 4*PLAYER_BUTTON_WIDTH,PLAYER_START_Y + PLAYER_BUTTON_HEIGTH,PUARROW_FASTRIGHT);

this->player->close();
this->player->hide();

fps = new FPSTest();
sprintf(fps_text_legend,"FPS : ---\n");
fps_text = new puText ( (int)(0.90 * (float)ww) , (int)(0.03 * (float)wh) );
fps_text -> setLabel(fps_text_legend);
fps_text -> setColour		 ( PUCOL_LABEL, 0.7f,0.8f,0.1f,1.0f ) ;

sprintf(info_text_legend,"");
info_text = new puText(li->w / 3, 5);
info_text -> setLabel(info_text_legend);
info_text -> reveal();

current_map_widget = 0;
//mapsWidget = (MapImage**) malloc( NUM_MAP_WIDGETS * sizeof(MapImage*) );

/* Other stuff */
time_t t = time ( NULL ) ;
printf("[%s] Creating controls...\n", ctime ( & t ));
this->kb = new Keyboard();
this->ms = new Mouse();
this->js = new Joystick();

t = time ( NULL ) ;
printf("[%s] Creating camera...\n", ctime ( & t ));
this->camera = new Camera();

t = time ( NULL ) ;
printf("[%s] Creating scenegraph...\n", ctime ( & t ));
this->scene = new Scenegraph(li,camera);

int lt;

doCritical(lt = li->loadingType, li->cs);

if( (lt == LOAD) || (lt == BRIEF))
	{
	// load objects
	this->loadScenario();
	}

this->nextState = this;

doCritical(canceled = li->canceled;
		   this->oldState = li->old_s,
	       li->cs);


/* Create Camera */
ck->update();
dt = ck->getDeltaTime();


doCritical(li->scenarioProgress = CAMERA_PROGRESS;
		   canceled = li->canceled 
		   , li->cs);

t = time ( NULL ) ;
printf("[%s] Creating land...\n", ctime ( & t ));
l = new Land(li->wrd_filename,li->wrdmap_filename,li);
//l -> addWorld(li->wrd_filename);

/*
t = time ( NULL ) ;
printf("[%s] Creating maps widgets...\n", ctime ( & t ));
mapsWidget[0] = new MapImage(l->getLevelsMatrix(),l->getHeigth(),l->getWidth(),0.01f,0.01f,0.3f,0.2f);
mapsWidget[1] = new MapImage(l->getExpoMatrix(),l->getHeigth(),l->getWidth(),0.01f,0.01f,0.3f,0.2f);
mapsWidget[2] = new MapImage(l->getShadowMatrix(),l->getHeigth(),l->getWidth(),0.01f,0.01f,0.3f,0.2f);
mapsWidget[3] = new MapImage(li->map_filename,l->getHeigth(),l->getWidth(),0.01f,0.01f,0.3f,0.2f);
*/

t = time ( NULL ) ;
printf("[%s] Adding Land...\n", ctime ( & t ));
scene->addLand(l);
t = time ( NULL ) ;
printf("[%s] Loading objects...\n", ctime ( & t ));
scene->load();
t = time ( NULL ) ;
printf("[%s] Adding sky...\n", ctime ( & t ));
scene->addSky();


//printf("WPN : %s\n",info->wpn_filename);
//printf("CMV : %s\n",info->cmv_filename);

t = time ( NULL ) ;
printf("[%s] Adding waypoints...\n", ctime ( & t ));
scene->addWaypoints(info->wpn_filename);
scene->hideWaypoints();
t = time ( NULL ) ;
printf("[%s] Adding movie...\n", ctime ( & t ));
scene->addMovie(info->cmv_filename);//"C:/Documents and Settings/Giorgio/Documenti/MSA/8/mondole.cmv");//li->mov_filename);
//scene->addWorld();

// Destroy all matrices
t = time ( NULL ) ;
printf("[%s] Destroying matrices...\n", ctime ( & t ));
l->freeAllMatrix();

doCritical(
    li->scenarioProgress = 1.0f;
    li->completed = true;
	li->s = this, li->cs);

inner_state = MOVIE_VIEW;
t = time ( NULL ) ;
printf("[%s] Starting all...\n", ctime ( & t ));
start();
}

ViewBriefingState::~ViewBriefingState()
{
delete this->camera;
//for(int i = 0; i < NUM_MAP_WIDGETS; i++) delete this->mapsWidget[i];
delete this->kb;
delete this->ms;
delete this->scene;
delete this->l;
delete this->ck;
delete this->fps;
}

void ViewBriefingState::load(const char* filename)
{
	
}

void ViewBriefingState::reset()
{
this->nextState = this;
}

void ViewBriefingState::display(void)
{
//glClearColor(0.2,0.2,0.7,1.0)

scene->display();

/*
for(int i = 0; i < NUM_MAP_WIDGETS; i++)
	mapsWidget[current_map_widget]->display();
*/

// display fps
sprintf(this->fps_text_legend,"FPS : %.1f",fps->test());
this->fps_text->setLegend(this->fps_text_legend);
puDisplay();
}

void ViewBriefingState::resize(int w, int h)
{

}

void ViewBriefingState::keyUp(unsigned char key, int x, int y)
{
kb->read(key,GLUT_UP,x,y);
}

void ViewBriefingState::keyDown(unsigned char key, int x, int y)
{
kb->read(key,GLUT_DOWN,x,y);

if(inner_state == FREE_VIEW)
	{
	if(key == 'm')
		{
		//if( mapsWidget[current_map_widget]->selected()) {current_map_widget++; if(current_map_widget >= NUM_MAP_WIDGETS) current_map_widget = 0;}
		}
	else if(key == 's') 
		{
		printf("Start\n");
		this->start();
		}
	}
else if(inner_state == MOVIE_VIEW)
	{
	if(key == 'e') this->end();
	if(kb->isPressed('p'))				   this->play();
	if(kb->isPressed('s'))				   this->stop();
	if(kb->isPressed('f'))				   this->forward();
	if(kb->isPressed('r'))				   this->rewind();
	}
}

void ViewBriefingState::specialUp(int key, int x, int y)
{
kb->read(key+PU_KEY_GLUT_SPECIAL_OFFSET,GLUT_UP,x,y);
}

void ViewBriefingState::specialDown(int key, int x, int y)
{
kb->read(key+PU_KEY_GLUT_SPECIAL_OFFSET,GLUT_DOWN,x,y);
}

void ViewBriefingState::motion(int newx, int newy)
{
puMouse(newx,newy);
}

void ViewBriefingState::passive(int newx, int newy)
{
puMouse(-1,-1,newx,newy);

/*
for(int i = 0; i < NUM_MAP_WIDGETS; i++)
	mapsWidget[i]->mouse(-1,-1,newx,newy);*/
}

void ViewBriefingState::mouse(int button, int state, int mouseX, int mouseY)
{
puMouse(button,state,mouseX,mouseY);

/*
for(int i = 0; i < NUM_MAP_WIDGETS; i++)
	mapsWidget[i]->mouse(button,state,mouseX,mouseY);*/
}

State* ViewBriefingState::idle(void)
{
float hot = this->scene->getHOT(this->camera->getCameraPosition()->xyz[SG_X],this->camera->getCameraPosition()->xyz[SG_Y]);
//float hot = 0.0f;

if(js->isWorking() && (inner_state == FREE_VIEW))
	{
	js->read();
	if(js->isDirection(JOYSTICK_LEFT))	camera->move(TURN_RIGHT,hot);
	if(js->isDirection(JOYSTICK_RIGHT)) camera->move(TURN_LEFT,hot);
	if(js->isDirection(JOYSTICK_UP))	camera->move(LOOK_DOWN,hot);
	if(js->isDirection(JOYSTICK_DOWN))	camera->move(LOOK_UP,hot);
	if(js->isPressed(JOYSTICK_X))       camera->move(GO_AHEAD,hot);
	if(js->isPressed(JOYSTICK_Y))		camera->move(GO_BACKWARDS,hot);
	if(js->isPressed(JOYSTICK_A))		camera->move(GO_UP,hot);
	if(js->isPressed(JOYSTICK_B))		camera->move(GO_DOWN,hot);
	if(js->isPressed(JOYSTICK_R))		camera->move(STRIFE_LEFT,hot);
	if(js->isPressed(JOYSTICK_L))		camera->move(STRIFE_RIGHT,hot);
	}

if(kb->isPressed(27)) exit(0);

//int i;
if(inner_state == FREE_VIEW)
	{
	if(kb->isPressed(GLUT_KEY_LEFT+PU_KEY_GLUT_SPECIAL_OFFSET))       /*if((mapsWidget[current_map_widget]->selected())) for(i = 0; i < NUM_MAP_WIDGETS; i++) mapsWidget[i]->moveLeft(1)  ; else */camera->move(TURN_LEFT,hot);
	if(kb->isPressed(GLUT_KEY_RIGHT+PU_KEY_GLUT_SPECIAL_OFFSET))      /*if((mapsWidget[current_map_widget]->selected())) for(i = 0; i < NUM_MAP_WIDGETS; i++) mapsWidget[i]->moveRight(1) ; else */camera->move(TURN_RIGHT,hot);
	if(kb->isPressed(GLUT_KEY_UP+PU_KEY_GLUT_SPECIAL_OFFSET))         /*if((mapsWidget[current_map_widget]->selected())) for(i = 0; i < NUM_MAP_WIDGETS; i++) mapsWidget[i]->moveUp(1)    ; else */camera->move(LOOK_UP,hot);
	if(kb->isPressed(GLUT_KEY_DOWN+PU_KEY_GLUT_SPECIAL_OFFSET))       /*if((mapsWidget[current_map_widget]->selected())) for(i = 0; i < NUM_MAP_WIDGETS; i++) mapsWidget[i]->moveDown(1)  ; else */camera->move(LOOK_DOWN,hot);
	if(kb->isPressed(GLUT_KEY_PAGE_UP+PU_KEY_GLUT_SPECIAL_OFFSET))    /*if((mapsWidget[current_map_widget]->selected())) for(i = 0; i < NUM_MAP_WIDGETS; i++) mapsWidget[i]->zoomIn(1)    ; else */camera->move(GO_UP,hot);
	if(kb->isPressed(GLUT_KEY_PAGE_DOWN+PU_KEY_GLUT_SPECIAL_OFFSET))  /*if((mapsWidget[current_map_widget]->selected())) for(i = 0; i < NUM_MAP_WIDGETS; i++) mapsWidget[i]->zoomOut(1)   ; else */camera->move(GO_DOWN,hot);
	if(kb->isPressed(GLUT_KEY_HOME+PU_KEY_GLUT_SPECIAL_OFFSET))	   /*if(!(mapsWidget[current_map_widget]->selected())) */camera->move(RESET,1);;
	if(kb->isPressed('a'))				   /*if(!(mapsWidget[current_map_widget]->selected())) */camera->move(GO_AHEAD,hot);;
	if(kb->isPressed('z'))				   /*if(!(mapsWidget[current_map_widget]->selected())) */camera->move(GO_BACKWARDS,hot);;
	if(kb->isPressed('.'))					/*if(!(mapsWidget[current_map_widget]->selected())) */camera->move(STRIFE_LEFT,hot);
	if(kb->isPressed(','))					/*if(!(mapsWidget[current_map_widget]->selected())) */camera->move(STRIFE_RIGHT,hot);
	}
else if(inner_state == MOVIE_VIEW)
	{
	this->scene->getMovie()->update();
	this->camera->setFilmPosition(this->scene->getMovie()->getLERPCameraPosition());
	}

if(nextState == this) {return nextState;}
else {State* tmpState = nextState; this->reset(); return tmpState;}
}

void ViewBriefingState::bindTextures()
{
/*for(int i = 0; i < NUM_MAP_WIDGETS; i++) mapsWidget[i]->bindTexture()*/;
}

void ViewBriefingState::createStates()
{
scene->createStates();
}

void ViewBriefingState::goBack()
{
// return splashscreen state
this->nextState = oldState;
LoadBriefingState* lbs = (LoadBriefingState*) oldState;
lbs->reload();
}

void ViewBriefingState::readBriefingFile(LoadingInfo* li)
{
doCritical(strcpy(snr_filename,li->snr_filename),li->cs);
}

void ViewBriefingState::loadScenario()
{
FILE *scenario_file;
char string[1024];

ObjectList *treeList = scene->getList(TREE_LIST);
ObjectList *buildingList = scene->getList(BUILDING_LIST);
ObjectList *textureList = scene->getList(TEXTURE_LIST);
ObjectList *facilityList = scene->getList(FACILITY_LIST);

//printf("File name: %s\n",snr_filename);

int i = 0;
bool go = true;

if((scenario_file = fopen(snr_filename,"r")) != NULL)
	{
	fgets(string,1024,scenario_file);
	fgets(string,1024,scenario_file);
	doCritical(fgets(info->dem_filename,1024,scenario_file);adjustFileName(info->dem_filename),info->cs);
	doCritical(fgets(info->map_filename,1024,scenario_file);adjustFileName(info->map_filename),info->cs);
	doCritical(fgets(info->obj_filename,1024,scenario_file);adjustFileName(info->obj_filename),info->cs);
	doCritical(fgets(info->tex_filename,1024,scenario_file);adjustFileName(info->tex_filename),info->cs);
	doCritical(fgets(info->wpn_filename,1024,scenario_file);adjustFileName(info->wpn_filename),info->cs);
	doCritical(fgets(info->cmv_filename,1024,scenario_file);adjustFileName(info->cmv_filename),info->cs);
	fgets(string,1024,scenario_file); // CAMERA
	loadCameraPosition(scenario_file);
	fgets(string,1024,scenario_file);
	fgets(string,1024,scenario_file);
	treeList->load(scenario_file);
	fgets(string,1024,scenario_file);
	buildingList->load(scenario_file);
	fgets(string,1024,scenario_file);
	textureList->load(scenario_file);
	fgets(string,1024,scenario_file);
	facilityList->load(scenario_file);
	fclose(scenario_file);
	}
else
	{
	printf("Cannot open scenario file %s for loading...\n",snr_filename);
	}
}

void ViewBriefingState::loadCameraPosition(FILE* f)
{
float x,y,z,h,p,r;
char c; 
fscanf(f,"%f%f%f%f%f%f%c",&x,&y,&z,&h,&p,&r,&c); // camera data line
scene->setCameraStartPosition(x,y,z,h,p,r);
}

void ViewBriefingState::start()
{
	//printf("In START\n");
	this->inner_state = MOVIE_VIEW;
		strcpy(info_text_legend,INFO_GO_TO_FREE_VIEW);
		this->info_text->setLegend(this->info_text_legend);
	this->scene->switchToMovieView();

	this->player->reveal();
	this->camera->switchToMovieView();
	/*
		for(int i = 0; i < NUM_MAP_WIDGETS; i++)
			mapsWidget[current_map_widget]->hide();*/
}

void ViewBriefingState::end()
{
	//printf("END\n");
	this->inner_state = FREE_VIEW;
		strcpy(info_text_legend,INFO_GO_TO_MOVIE_VIEW);
		this->info_text->setLegend(this->info_text_legend);
	this->scene->switchToEditingView();
	this->player->hide();
	this->stop();
	this->camera->switchToEditingView();

	/*	for(int i = 0; i < NUM_MAP_WIDGETS; i++)
			mapsWidget[current_map_widget]->reveal();*/
}

void ViewBriefingState::play()
{
	this->scene->getMovie()->play();
	this->player->hide();
	this->info_text->hide();
	this->fps_text->hide();
}

void ViewBriefingState::stop()
{
	this->scene->getMovie()->stop();
	this->player->reveal();
	this->info_text->reveal();
	this->fps_text->reveal();
} 

void ViewBriefingState::forward()
{
	this->scene->getMovie()->forward();
}

void ViewBriefingState::rewind()
{
	this->scene->getMovie()->rewind();
}

void ViewBriefingState::playm_cb ( puObject * p)
{
puObject* pr = p->getParent();
ViewBriefingState* vbs = (ViewBriefingState*) pr->getUserData();

vbs->play();
}

void ViewBriefingState::stopm_cb ( puObject * p)
{
puObject* pr = p->getParent();
ViewBriefingState* vbs = (ViewBriefingState*) pr->getUserData();

vbs->stop();
}